using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

[RequireComponent(typeof(UISprite))]
public class ClipAnimation : MonoBehaviour
{
    public enum SwapMode
    {
        Loop,
        Once,
    }

    class Clip
    {
        UIAtlas atlas;
        SwapMode playMode;

        public UIAtlas Atlas
        {
            get
            {
                return atlas;
            }
            set
            {
                atlas = value;
            }
        }

        public SwapMode Mode
        {
            get
            {
                return playMode;
            }
            set
            {
                playMode = value;
            }
        }

        public Clip(UIAtlas _atlas)
        {
            atlas = _atlas;
            playMode = ClipAnimation.SwapMode.Loop;
        }
    }
	
	public int FPS = 15;
	
	[HideInInspector]
    [SerializeField]
    int mFPS = 30;
    [HideInInspector]
    [SerializeField]
    string mPrefix = "";
    [HideInInspector]
    [SerializeField]
    bool mLoop = true;

    UISprite mSprite;
    float mDelta = 0f;
    int mIndex = 0;
    bool mActive = true;
    List<string> mSpriteNames = new List<string>();

    public string filePath;

    Dictionary<string, Clip> clipAnimations = new Dictionary<string, Clip>();

    UIAtlas[] atlases;
    UISprite sprite;
    string _currentClip;

    /// <summary>
    /// Number of frames in the animation.
    /// </summary>

    public int frames { get { return mSpriteNames.Count; } }

    /// <summary>
    /// Animation framerate.
    /// </summary>

    public int framesPerSecond { get { return mFPS; } set { mFPS = value; } }

    /// <summary>
    /// Set the name prefix used to filter sprites from the atlas.
    /// </summary>

    public string namePrefix { get { return mPrefix; } set { if (mPrefix != value) { mPrefix = value; RebuildSpriteList(); } } }

    /// <summary>
    /// Set the animation to be looping or not
    /// </summary>

    public bool loop { get { return mLoop; } set { mLoop = value; } }

    /// <summary>
    /// Returns is the animation is still playing or not
    /// </summary>

    public bool isPlaying { get { return mActive; } }

    /// <summary>
    /// Return the current clip's name;
    /// </summary>
    public string currentClip { get { return _currentClip; } }

    void Start()
    {
        sprite = GetComponent<UISprite>();

        UnityEngine.Object[] objects;
        objects = Resources.LoadAll(filePath, typeof(UIAtlas));

        for (int i = 0; i < objects.Length; i++)
        {
            Clip c = new Clip(objects[i] as UIAtlas);
            clipAnimations.Add(objects[i].name, c);
        }

        // Rebuild the sprite list first thing.
        RebuildSpriteList();

        Play("idle",FPS);
    }

    /// <summary>
    /// Play the animation.
    /// </summary>
    public void Play(string clipName)
    {
        if (_currentClip == clipName) return;
        try
        {
            mActive = true;
            string atlasName = filePath + "_" + clipName;
            Clip clip = clipAnimations[atlasName];
            sprite.atlas = clip.Atlas;
            _currentClip = clipName;

            RebuildSpriteList();
			
            mSprite.MakePixelPerfect();

            mFPS = FPS;

            if (clip.Mode == SwapMode.Loop)
            {
                mLoop = true;
            }
            else if (clip.Mode == SwapMode.Once)
            {
                mLoop = false;
            }
        }
        catch (Exception e)
        {
            //Debug.Log("Play error = " + e);
        }
    }

    /// <summary>
    /// Play the animation.
    /// </summary>
    public void Play(string clipName, int frame)
    {
        if (_currentClip == clipName) return;
		try
        {
	        mActive = true;
	        string atlasName = filePath + "_" + clipName;
	        Clip clip = clipAnimations[atlasName];
	        sprite.atlas = clip.Atlas;
	        _currentClip = clipName;
	
	        RebuildSpriteList();
			
			mSprite.MakePixelPerfect();
	
	        mFPS = frame;
	
	        if (clip.Mode == SwapMode.Loop)
	        {
	            mLoop = true;
	        }
	        else if (clip.Mode == SwapMode.Once)
	        {
	            mLoop = false;
	        }
		}
		catch (Exception e)
        {
            //Debug.Log("Play error = " + e);
        }
    }

    /// <summary>
    /// Stop the current animation.
    /// </summary>
    public void Stop()
    {
        mActive = false;
    }

    /// <summary>
    /// CrossFade to another clip
    /// </summary>
    public void CrossFade(string clipName)
    {
        //TODO
    }

    /// <summary>
    /// Advance the sprite animation process.
    /// </summary>

    void Update()
    {
        if (mActive && mSpriteNames.Count > 1 && Application.isPlaying && mFPS > 0f)
        {
            mDelta += Time.deltaTime;
            float bitRate = mSpriteNames.Count / 15>=1?mSpriteNames.Count / 15:1; //×Ô¶šÒå»ù±Ÿ±ÈÂÊ//
            float rate = bitRate / mFPS;

            if (rate < mDelta)
            {

                mDelta = (rate > 0f) ? mDelta - rate : 0f;
                if (++mIndex >= mSpriteNames.Count)
                {
                    mIndex = 0;
                    mActive = loop;
                }

                if (mActive)
                {
                    mSprite.spriteName = mSpriteNames[mIndex];
                    mSprite.MakePixelPerfect();
                }
            }
        }
    }

    /// <summary>
    /// Rebuild the sprite list after changing the sprite name.
    /// </summary>

    void RebuildSpriteList()
    {
        if (mSprite == null) mSprite = GetComponent<UISprite>();
        mSpriteNames.Clear();

        if (mSprite != null && mSprite.atlas != null)
        {
            List<UIAtlas.Sprite> sprites = mSprite.atlas.spriteList;

            for (int i = 0, imax = sprites.Count; i < imax; ++i)
            {
                UIAtlas.Sprite sprite = sprites[i];

                if (string.IsNullOrEmpty(mPrefix) || sprite.name.StartsWith(mPrefix))
                {
                    mSpriteNames.Add(sprite.name);
                }
            }
            mSpriteNames.Sort();
        }
    }

    /// <summary>
    /// Reset the animation to frame 0 and activate it.
    /// </summary>

    public void Reset()
    {
        mActive = true;
        mIndex = 0;
    }
}
